#include "head.h"
//插入车位表
int insert_park(park * p){
    char sql[256];
    char * errmsg;
    //拼接字符串
    sprintf(sql,"insert into park(person_id,park_number,park_type,park_location) values('%d','%s','%s','%s');"
            ,p->person_id,p->park_number,p->park_type,p->park_location);
    int rc = sqlite3_exec(db,sql,NULL,NULL,&errmsg) ;
    if(rc!=SQLITE_OK ){
        fprintf(stderr,"table park插入失败：%s\n",errmsg);
        sqlite3_free(errmsg) ;
        return -1;
    }
    printf("插入成功！\n");
    return 0;
}
//修改车位表
int update_park(const char *old_park_number, int choice,park * p) {
    char sql[256];
    char *errmsg=NULL;
    //拼接字符串
    //根据选择构建不同的sql语句
    switch(choice) {
        case 1: // 修改业主id
            sprintf(sql, "update park set person_id = %d where park_number = '%s';",
                    p->person_id, old_park_number);
            break;
        case 2: // 修改车位编号
            sprintf(sql, "update park set park_number = '%s' where park_number = '%s';",
                    p->park_number, old_park_number);
            break;
        case 3: // 修改车位类型
            sprintf(sql, "update park set park_type = '%s' where park_number = '%s';",
                    p->park_type, old_park_number);
            break;
        case 4: // 修改车位位置
            sprintf(sql, "update park set park_location = '%s' where park_number = '%s';",
                    p->park_location, old_park_number);
            break;
        default:
            printf("选择无效！\n");
            return -1;
    }
    int rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "table park修改失败：%s\n", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    // 检查是否真正修改了记录
    //检查数据库的更新操作是否执行成功
    int changes = sqlite3_changes(db);
    if (changes == 0) {
        printf("未找到车位编号为 '%s' 的记录，修改失败！\n", old_park_number);
        return -1;
    }
    printf("修改成功！\n");
    return 0;
}
//删除车位表
// 根据车位编号删除车位信息
int delete_park(char *park_number) {
    char sql[256];
    char *errmsg;
    // 拼接字符串
    sprintf(sql, "delete from park where park_number = '%s';", park_number);
    int rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "车位删除失败：%s\n", errmsg);
        sqlite3_free(errmsg);
        return -1;
    }
    // 检查是否删除了记录
    //获取最近一次SQL操作影响的数据行数
    int changes = sqlite3_changes(db);
    //返回正整数，表示成功删除了多条记录
    if (changes > 0) {
        printf("成功删除车位编号为 '%s' 的记录\n", park_number);
    } else {
        printf("没有找到车位编号为 '%s' 的记录\n", park_number);
    }
    //将删除操作影响的行数作为函数的返回值，返回实际删除的记录数
    return changes;
}
//查询车位表
int query_park(char * park_number){
    sqlite3_stmt * stmt;//预编译语句句柄
    const char * sql ="select person_id as 人员编号,park_number as 车位号,park_type as 车位类型,park_location as 区域 from park where park_number= ? ;";
    int rc = sqlite3_prepare_v2 (db,sql,-1,&stmt,NULL) ;
    if(rc!=SQLITE_OK ){
        fprintf(stderr,"park查询预编译出错：%s\n", sqlite3_errmsg(db) );
        sqlite3_finalize(stmt);
        return -1;
    }
    //绑定参数
    //语句句柄，？的位置，参数值，参数长度，参数的销毁方式
    sqlite3_bind_text(stmt,1,park_number,-1,SQLITE_TRANSIENT ) ;
    //执行查询sql语句
    //首先设为没有找到数据
    int found = 0;
    while(sqlite3_step(stmt)==SQLITE_ROW){
        //判断是否找到了数据，才输出表头
        if (!found) {
            // 第一次找到数据时才输出表头
            int park_head_count = sqlite3_column_count(stmt);
            for (int i = 0; i < park_head_count; i++) {
                printf("%s|\t", sqlite3_column_name(stmt, i));
            }
            printf("\n");
            //值为1，表示只输出一次表头
            found = 1;
        }
        //读取当前指向行的各个列的数据
        int id = sqlite3_column_int(stmt,0);
        const char * n = (const char *)sqlite3_column_text(stmt,1);
        const char * t = (const char *)sqlite3_column_text(stmt,2);
        const char * l = (const char *)sqlite3_column_text(stmt,3);
        printf("输出查询结果：| %d | %s | %s | %s |\n",id,n,t,l);
    }

    // 如果没有找到记录
    if (!found) {
        printf("没有找到车位编号为 '%s' 的记录\n", park_number);
    }
    //释放语句句柄
    sqlite3_finalize(stmt);
    return found;
}
//关联查询，根据车位编号查询住户信息
int query_park_person(char * park_number){
    const char * sql =
                        "select "
                        "p.person_id as 人员编号, "
                        "p.park_number as 车位号 , "
                        "p.park_type as 车位类型, "
                        "p.park_location as 区域, "
                        "r.name as 姓名, "
                        "r.phone as 电话, "
                        "r.id_card as 身份证号, "
                        "r.time as 入住日期 "
                        "from park p "
                        "left join resident r on p.person_id = r.person_id "
                        "where p.park_number = ?;";
    sqlite3_stmt * stmt;//定义语句句柄
    //调用预编译方法，进行语句预编译处理，返回预编译语句句柄
    int rc = sqlite3_prepare_v2 (db,sql,-1,&stmt,NULL) ;
    //判断预编译是否成功
    if(rc!=SQLITE_OK ){
        fprintf(stderr,"park关联查询预编译出错：%s\n", sqlite3_errmsg(db) );
        return -1;
    }
    //绑定参数
    sqlite3_bind_text(stmt,1,park_number,-1,SQLITE_TRANSIENT ) ;
    //执行查询sql语句
    //首先设为没有找到数据
    int found = 0;
    while(sqlite3_step(stmt)==SQLITE_ROW){
        if (!found) {
            // 第一次找到数据时才输出表头
            //获取查询结果集的列数
            int park_head_count = sqlite3_column_count(stmt);
            for (int i = 0; i < park_head_count; i++) {
                printf("%s|\t", sqlite3_column_name(stmt, i));
            }
            printf("\n");
            //值为1，表示只输出一次表头
            found = 1;
        }
        //读取当前指向行的各个列的数据
        //sqlite3_column_int，从查询结果提取整数值
        int id = sqlite3_column_int(stmt,0);
        //const表示指针指向的内容是只读的，防止意外修改sqlite3返回的数据，导致程序崩溃
        //sqlite3_column_text() 返回的是sqlite3内部管理的内存指针
        //sqlite3_column_text，从查询结果中提取文本值（字符串）
        const char * n = (const char *)sqlite3_column_text(stmt,1);
        const char * t = (const char *)sqlite3_column_text(stmt,2);
        const char * l = (const char *)sqlite3_column_text(stmt,3);
        const char * name = (const char *)sqlite3_column_text(stmt,4);
        const char * phone = (const char *)sqlite3_column_text(stmt,5);
        const char * id_card = (const char *)sqlite3_column_text(stmt,6);
        const char * time = (const char *)sqlite3_column_text(stmt,7);
        printf("输出查询结果：| %d | %s | %s | %s | %s | %s | %s | %s |\n",
               id, n,t,l,name ,phone ,id_card ,time);
    }

    // 如果没有找到记录
    if (!found) {
        printf("没有找到车位编号为 '%s' 的记录\n", park_number);
    }
    sqlite3_finalize(stmt) ;
    //返回查询操作的结果状态，表示是否找到了记录
    return found;
}
void main_park(){
     printf("1.增加车位信息 2.修改车位信息 3.删除车位信息 4.查询车位信息 5.退出\n");
     int choose_park;//定义输入选择变量
     //d控制循环
     int d=1,e=0;
     park pa;//定义车位结构体变量
     char old_park_number[20];//定义原来的车位编号
     //按车位编号查询
     char search_park_number[20];//定义要查询的车位编号
     choose_park= hcq(choose_park);//只能是有效整数
     while(d){
         //第一次e为0，不再次输出菜单
         if(e!=0){
             printf("1.增加车位信息 2.修改车位信息 3.删除车位信息 4.查询车位信息 5.退出\n");
             choose_park= hcq(choose_park);//只能是有效整数
         }
         //e非0，表示执行某个case之后,能循环输出显示菜单
         e++;
         switch(choose_park ){
             case 1:
                 //插入功能
                 printf("输入业主id: ");
                 scanf("%d",&pa.person_id);
                 printf("输入车位编号： ");
                 scanf("%s",pa.park_number);
                 printf("输入车位类型： ");
                 scanf("%s",pa.park_type);
                 printf("输入车位位置： ");
                 scanf("%s",pa.park_location);
                 insert_park(&pa) ;
                 break;
             case 2:
                 //修改功能
                 printf("输入要修改的车位编号： ");
                 scanf("%s", old_park_number);
                 //将查询的老车位编号定义给found
                 int found = query_park(old_park_number);
                 //如果没有找到该车位编号
                 if (!found) {
                     printf("车位编号 '%s' 不存在！\n", old_park_number);
                     break;
                 }
                 printf("该车位存在，请修改：\n");
                 int choice;
                 //根据序号的选择，修改相应的内容
                 printf("1.修改业主id 2.修改车位编号 3.修改车位类型 4.修改车位位置\n ");
                 printf("选择要修改的序号:");
                 scanf("%d",&choice);
                 //在测试中发现，当选择其中一个修改的时候，修改成功后，会直接结束，不能循环输出修改菜单，需要再次选择，才能继续修改
                 // 根据选择输入相应的数据
                 switch(choice) {
                     case 1:
                         printf("输入新业主id: ");
                         scanf("%d", &pa.person_id);
                         break;
                     case 2:
                         printf("输入新车位编号: ");
                         scanf("%s", pa.park_number);
                         break;
                     case 3:
                         printf("输入新车位类型: ");
                         scanf("%s", pa.park_type);
                         break;
                     case 4:
                         printf("输入新车位位置: ");
                         scanf("%s", pa.park_location);
                         break;
                     default:
                         printf("选择无效！\n");
                         break;
                 }
                 update_park(old_park_number,choice,&pa) ;
                 break;
             case 3:
                 //删除功能
                 printf("输入删除的车位编号: ");
                 scanf("%s", search_park_number);
                 delete_park(search_park_number);
                 break;
             case 4:
                 //查询功能
                 printf("1.查询车位编号 2.查询该车位编号的个人信息\n");
                 printf("请选择查询序号: ");
                 int query_choice;//定义查询条件
                 scanf("%d", &query_choice);
                 printf("输入要查询的车位编号: ");
                 scanf("%s", search_park_number);
                 if (query_choice == 1) {
                     // 只查询车位信息
                     query_park(search_park_number);
                 } else if (query_choice == 2) {
                     // 查询车位信息和关联的住户信息
                     query_park_person(search_park_number);
                 } else {
                     printf("查询输入错误！\n");
                 }
                 break;
             case 5:
                 d=0;
                 break;
             default:
                 break;
         }
     }

}
